package utils;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

public class BikeCommandUtil {
    public static byte sender;
    public static byte length;
    public static byte[] operationCode;
    public static byte[] data; // 除去校验和和结束符
    public static byte checksum;
    public static byte end;
    public static String operatorCommand;
    public static double[] units = {0.01, 0.01, 0.5, 0.5, 1, 1, 1, 1, 1, 1, 1, 1, 0.1, 1, 1};
    public static int[] bitsForEvery = {2, 2, 2, 2, 3, 2, 2, 2, 2, 2, 1, 1, 1, 2, 2};

    public static void parseCommand(String command) {
        // 将十六进制字符串转换为字节数组
        byte[] bytes = hexStringToByteArray(command);

        // 提取各个部分
        sender = bytes[0];
        length = bytes[1];
        operationCode = Arrays.copyOfRange(bytes, 2, 4);
        data = Arrays.copyOfRange(bytes, 4, bytes.length - 2); // 除去校验和和结束符
        checksum = bytes[bytes.length - 2];
        end = bytes[bytes.length - 1];
        operatorCommand = command.substring(4, 8);

        // 打印解析命令后的各种信息
        print();

        // 验证Length是否错误
        if ((length & 0xFF) != operationCode.length + data.length + 1) {
            System.out.println("Length字段不符合要求");
            return;
        }

        // 验证校验码是否错误
        if (calculateChecksum(operationCode, data) != (checksum & 0xFF)) {
            System.out.println("计算所得的校验码为：" + String.format("0x%02X", calculateChecksum(operationCode, data)));
            System.out.println("校验码不一致");
            return;
        }

        // 根据具体的命令处理
        processOperatorCommand(operatorCommand);
    }

    // 计算校验和
    public static int calculateChecksum(byte[] operationCode, byte[] data) {
        int sum = 0;
        for (byte b : operationCode) {
            sum += (b & 0xFF); // 确保将字节转换为无符号整数
        }
        for (byte b : data) {
            sum += (b & 0xFF); // 确保将字节转换为无符号整数
        }
        return sum & 0xFF; // 取低位字节作为校验和
    }

    public static void processOperatorCommand(String operatorCommand) {
        switch (operatorCommand) {
            case CommandConstants.IndoorBikeData:
                // 调用工具类专门解析传入过来的数据
                System.out.println();
                System.out.println("计算所得的Bike参数如下：");
                parse(data);
                break;
            case CommandConstants.FitnessMachineControlPoint:
                System.out.println("This is Fitness Machine Control Point");
                break;
            case CommandConstants.ManufacturerNameString:
                String deviceName = byteArrayToString(data);
                System.out.println("制造商名称为： " + deviceName);
                break;
            case CommandConstants.DeviceName:
                String manufacturerName = byteArrayToString(data);
                System.out.println("设备名称为： " + manufacturerName);
                break;
            case CommandConstants.HardwareRevisionString:
                String HardwareName = byteArrayToString(data);
                System.out.println("硬件名称为： " + HardwareName);
                break;
            case CommandConstants.FirmwareRevisionString:
                String FirmwareName = byteArrayToString(data);
                System.out.println("固件名称为： " + FirmwareName);
                break;
            default:
                System.out.println("未知的操作命令: " + operatorCommand);
        }
    }

    // 将十六进制字符串转换为字节数组
    public static byte[] hexStringToByteArray(String s) {
        int len = s.length();
        byte[] data = new byte[len / 2];
        for (int i = 0; i < len; i += 2) {
            data[i / 2] = (byte) ((Character.digit(s.charAt(i), 16) << 4)
                    + Character.digit(s.charAt(i + 1), 16));
        }
        return data;
    }

    // 将字节数组转换为十六进制字符串，直接转化，不用ASCII转化
    public static String bytesToHex(byte[] bytes) {
        StringBuilder sb = new StringBuilder();
        for (byte b : bytes) {
            sb.append(String.format("%02X ", b));
        }
        return sb.toString().trim();
    }

    // 将字节数组转化为字符串，使用对应ASCII码转化
    public static String byteArrayToString(byte[] byteArray) {
        StringBuilder sb = new StringBuilder();
        for (byte b : byteArray) {
            sb.append((char) (b & 0xFF));
        }
        return sb.toString();
    }

    public static void print() {
        // 打印解析结果
        System.out.println("Sender: " + String.format("0x%02X", sender));
        System.out.println("Length: " + String.format("0x%02X", length));
        System.out.println("Operation Code: " + bytesToHex(operationCode));
        System.out.println("Data: " + bytesToHex(data));
        System.out.println("Checksum: " + String.format("0x%02X", checksum));
        System.out.println("End: " + String.format("0x%02X", end));
    }

    // 解析FTMS value，输出各种所需参数
    public static void parseFitnessData(byte[] bytes) {
        if (bytes.length < 10) {
            System.out.println("数据长度不足");
            return;
        }

        // String str = "6400 2209 CF00 0C00 3C00";
        // 解析速度 (Speed)
        byte speedLow = bytes[2]; // 低字节
        byte speedHigh = bytes[3]; // 高字节
        int speed = (speedHigh << 8) | (speedLow & 0xFF); // 合并高低字节
        System.out.println("Speed: " + speed * 0.01 + " km/h");

        // 解析踏频 (Cadence)
        int cadenceLow = bytes[4]; // 低字节
        int cadenceHigh = bytes[5]; // 高字节
        int cadence = (cadenceHigh << 8) | (cadenceLow & 0xFF); // 合并高低字节
        System.out.println("Cadence: " + cadence * 0.5 + " RPM");

        // 解析阻力级别 (Resistance Level)
        int resistanceLevelLow = bytes[6]; // 低字节
        int resistanceLevelHigh = bytes[7]; // 高字节
        int resistanceLevel = (resistanceLevelHigh << 8) | (resistanceLevelLow & 0xFF);
        System.out.println("Resistance Level: " + resistanceLevel);

        // 解析功率 (Power)
        int powerLow = bytes[8]; // 低字节
        int powerHigh = bytes[9]; // 高字节
        int power = (powerHigh << 8) | (powerLow & 0xFF); // 合并高低字节
        System.out.println("Power: " + power + " W");

        // 解析标志位 (Flag define) - 这里需要根据具体的定义来解析
        // 假设第一个字节是标志位
        int flagDefine = bytes[0]; // 直接取值
        System.out.println("Flag Define: " + flagDefine);
    }

    public static List<Integer> parse(byte[] bytes){
        List<Integer> ans = new ArrayList<>();
        bytes[0] |= 0x01;
        int code = (int) parseData(bytes, 0, 2, 1);
        List<Integer> list = new ArrayList<>();

        for (int i = 0; i < 15; i++) {
            if (((code >> i) & 1) == 1) {
                list.add(i);
            }
        }
        int index = 2;
        for (int i : list) {
            int value = parseData(bytes, index, bitsForEvery[i], units[i]);
            switch (i) {
                case 0:
                    System.out.println("Instantaneous Speed: " + value + " km/h");
                    ans.add(value);
                    break;
                case 2:
                    System.out.println("Instantaneous Cadence: " + value + " RPM");
                    ans.add(value);
                    break;
                case 5:
                    System.out.println("Resistance Level: " + (int)value);
                    ans.add(value);
                    break;
                case 6:
                    System.out.println("Instantaneous Power: " + (int)value + " W");
                    ans.add(value);
                    break;
            }
            index += bitsForEvery[i];
        }
        return ans;
    }

    public static int parseData(byte[] bytes, int offset, int len, double scale){
        int value = 0;
        for(int i = len - 1; i >= 0; i--){
            value = (value << 8) | (bytes[offset + i] & 0xFF);
        }
        return value;
    }

}
